<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件阶段</title>
</head>

<body>
    <div id="outer">
        <div id="inner">
            <button id="btn">Click me</button>
        </div>
    </div>

</body>

</html>
<script>
// 在 JavaScript 中，一个事件会经历三个阶段：捕获阶段（capturing phase）、目标阶段（target phase）和冒泡阶段（bubbling phase）。这三个阶段描述了事件从文档树的根节点向目标元素传播以及从目标元素向根节点传播的过程。

// 捕获阶段：事件从文档树的根节点开始向下传播，直到达到事件的目标元素。在这个阶段，事件会依次触发经过的每个元素上注册的捕获阶段的事件处理程序。

// 目标阶段：事件到达目标元素后，在目标元素上触发相应的事件处理程序。这是事件传播的中间阶段。

// 冒泡阶段：事件从目标元素开始向上层元素传播，直到达到文档树的根节点。在这个阶段，事件会依次触发经过的每个元素上注册的冒泡阶段的事件处理程序。


// 不是所有的事件都会在三个阶段中都执行事件处理程序，具体取决于事件类型和事件监听器的设置。

// 例如，focus 和 blur 事件只在捕获阶段和目标阶段执行事件处理程序，而不会在冒泡阶段执行。另外，如果在事件监听器中调用了 event.stopPropagation() 方法来停止事件传播，那么相应阶段后续的事件处理程序就不会被执行。

// 默认情况下，大多数事件都会在冒泡阶段执行事件处理程序，因为这样可以让事件的处理更加灵活。例如，如果一个按钮嵌套在一个 div 元素中，当用户单击按钮时，可以通过在 div 元素上添加单击事件处理程序来处理整个区域的单击事件，而不需要在每个按钮上都添加单击事件处理程序。

// 总之，在 JavaScript 中，事件传播分为三个阶段：捕获阶段、目标阶段和冒泡阶段。但并不是所有的事件都会在这三个阶段中都执行事件处理程序，具体取决于事件类型和事件监听器的设置。\

// addEventListener 默认是在事件冒泡阶段执行事件处理程序
    const outer = document.getElementById('outer');
    const inner = document.getElementById('inner');
    const btn = document.getElementById('btn');

    outer.addEventListener('click', function () {
        console.log('outer clicked');
    });

    inner.addEventListener('click', function () {
        console.log('inner clicked');
    });

    btn.addEventListener('click', function () {
        console.log('button clicked');
    });

    // addEventListener  最后一个参数为true，表示在事件的捕获阶段执行事件处理程序
    outer.addEventListener('click', function () {
        console.log('outer clicked');
    }, true);

    inner.addEventListener('click', function () {
        console.log('inner clicked');
    }, true);

    // 在 addEventListener 方法中，最后一个参数是一个布尔值，用于指定事件处理程序是在捕获阶段执行还是在冒泡阶段执行。这个参数通常称为 useCapture。

    // 如果 useCapture 参数为 true，则事件处理程序将在捕获阶段执行，即在事件传播的第一个阶段。如果 useCapture 参数为 false（默认值），则事件处理程序将在冒泡阶段执行，即在事件传播的最后一个阶段。

    // 需要注意的是，无论是在捕获阶段还是在冒泡阶段执行事件处理程序，都是从外层元素向内层元素传播的过程。useCapture 参数的设置只影响事件处理程序的触发顺序，而不会影响事件的传播方向。


    // 事件传播是从文档树的根节点开始，沿着 DOM 树向下传播到目标元素，然后再从目标元素开始沿着 DOM 树向上冒泡，直到传播到文档树的根节点。在这个过程中，事件处理程序的执行顺序取决于 useCapture 参数的值。

    // 无论是在捕获阶段还是在冒泡阶段执行事件处理程序，都是从外层元素向内层元素传播的过程。具体来说：

    // 在捕获阶段，事件从文档树的根节点开始向下传播，依次经过每个祖先元素直到目标元素，然后触发目标元素上的事件处理程序。因此，如果在捕获阶段执行事件处理程序，处理程序会先于目标元素的事件处理程序被执行，并且执行顺序是从外层元素到内层元素。
    // 在冒泡阶段，事件从目标元素开始向上冒泡，依次经过每个祖先元素直到文档树的根节点，然后触发每个祖先元素上的事件处理程序。因此，如果在冒泡阶段执行事件处理程序，处理程序会后于目标元素的事件处理程序被执行，并且执行顺序是从内层元素到外层元素。
    // 总之，无论是在捕获阶段还是在冒泡阶段执行事件处理程序，都是从外层元素向内层元素传播的过程。
</script>